import * as Cesium from 'cesium';
import { EngineObject, ESRtsFeatureEditing } from "earthsdk3";
import { ESCesiumViewer } from 'earthsdk3-cesium';
import { createNextAnimateFrameEvent } from "earthsdk3";
import { ESRtsTileset2 } from "./index"
interface LayerType {
    dataset: number,
    layer: number,
    value: { visible: boolean, color: string | null },
}

// 将十六进制颜色字符串（如"#FFFFFF"）转换为RGBA字符串，然后将RGBA字符串解析为归一化的RGBA数组
function hexToNormalizedRgbaArray(hex: string): number[] {
    // Step 1: 十六进制转RGBA字符串
    let r = 0, g = 0, b = 0, a = 1;

    // 移除#号并处理简写形式
    hex = hex.replace('#', '');
    if (hex.length === 3) {
        hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
    }

    // 解析RGB成分
    if (hex.length >= 6) {
        r = parseInt(hex.substring(0, 2), 16);
        g = parseInt(hex.substring(2, 4), 16);
        b = parseInt(hex.substring(4, 6), 16);
    }

    // 解析Alpha成分（如果有）
    if (hex.length === 8) {
        const alphaHex = hex.substring(6, 8);
        a = parseInt(alphaHex, 16) / 255; // 0-255转0.0-1.0
    }

    // 生成RGBA字符串
    const rgbaString = `rgba(${r},${g},${b},${a})`;

    // Step 2: 将RGBA字符串转换为归一化数组
    return [
        r / 255, // R [0-1]
        g / 255, // G [0-1]
        b / 255, // B [0-1]
        a        // A [0-1] (已处理过)
    ];
}


export class CzmESRtsTileset2<T extends ESRtsTileset2 = ESRtsTileset2> extends EngineObject<T> {
    static readonly type = this.register<ESRtsTileset2, ESCesiumViewer>('ESCesiumViewer', ESRtsTileset2.type, this);
    constructor(sceneObject: T, czmViewer: ESCesiumViewer) {
        super(sceneObject, czmViewer);
        const viewer = czmViewer.viewer;
        if (!viewer) {
            console.warn(`viewer is undefined!`);
            return;
        }
        // 添加高亮和移除高亮事件
        {
            this.d(sceneObject.highlightInner3DtilesetEvent.don((es3dtileset: ESRtsFeatureEditing) => {
                es3dtileset.strokeFeature([]);
                const don = es3dtileset.d(es3dtileset.tilesetReady.donce((tileset) => {
                    tileset.allTilesLoaded.addEventListener(() => {
                        const feature = tileset?._root?._content?._model?._featureTables[0]?._features[0];
                        if (feature) {
                            es3dtileset.strokeFeature([feature], Cesium.Color.LIME.toBytes().map(v => v / 255));
                            // if (isFlyTo(viewer.scene, tileset)) {
                            //     es3dtileset.flyTo();
                            // }
                        } else {
                            console.warn(`tileset?._root?._content?._model?._featureTables[0]?._features[0] is undefined !`, tileset);
                        }
                        don();
                    })
                }));
                const url = es3dtileset.url as string;
                const time = Date.now();
                if (url.includes('?reload=')) {
                    es3dtileset.url = url.replace(/\?reload=\d+/, `?reload=${time}`);
                } else {
                    es3dtileset.url = url + `?reload=${time}`;
                }
            }))


            this.d(sceneObject.removeHighlightInner3DtilesetEvent.don((es3dtileset) => { es3dtileset.strokeFeature([]); }))
        }

        //图层配置
        {
            this.d(sceneObject.es3DTileset.tilesetReady.don((tileset: Cesium.Cesium3DTileset) => {
                const styleUpdate = () => {
                    const configs = sceneObject.layerConfig as unknown as LayerType[] | undefined;
                    if (!configs) {
                        tileset.style = undefined;
                        return;
                    }
                    const colorBlendMode = sceneObject.colorBlendMode;
                    const evaluateColor = (feature: Cesium.Cesium3DTileFeature, result: Cesium.Color | undefined) => {
                        try {
                            
                            if (feature.getPropertyIds().includes("materialName")) {
                                return Cesium.Color.clone(Cesium.Color.WHITE, result);
                            }
                            const ids = feature.getProperty('layer');
                            const ds = feature.getProperty('dataset');
                            const newIds = ids.toString() as string;
                            const dataset = ds.toString() as string;
                            const config = configs.find(e => ((e.dataset).toString() === dataset) && ((e.layer).toString() === newIds));
                            if (config && config.value.color) {
                                const color = config.value.color as string;
                                return Cesium.Color.fromCssColorString(color, result);
                            }
                            // @ts-ignore
                            const filterConfig = configs.filter(e => e.dataset.toString() === dataset)

                            if ((filterConfig.length == 1) && (filterConfig[0].value.color)) {
                                const color = filterConfig[0].value.color as string;
                                return Cesium.Color.fromCssColorString(color, result);

                            } else {
                                return Cesium.Color.clone(Cesium.Color.WHITE, result);
                            }
                        } catch (error) {
                            console.warn(error);
                            return Cesium.Color.clone(Cesium.Color.WHITE, result);
                        }
                    };
                    const evaluateShow = (feature: Cesium.Cesium3DTileFeature) => {
                        try {
                            if (feature.getPropertyIds().includes("id")) {
                                const vals = Object.entries(sceneObject.visJson);
                                for (let i = 0; i < vals.length; i++) {
                                    const val:any = vals[i];
                                    if (feature.getProperty("id").toString() === val[0]) {
                                        return val[1];
                                    }
                                }
                            }
                            if (feature.getPropertyIds().includes("materialName")) {
                                return true;
                            }
                            const ids = feature.getProperty('layer');
                            const ds = feature.getProperty('dataset');
                            const newIds = ids.toString() as string;
                            const dataset = ds.toString() as string;
                            const config = configs.find(e => ((e.dataset).toString() === dataset) && ((e.layer).toString() === newIds));
                            if (config && (config.value.visible === false)) {
                                return false;
                            }
                            if (config && (config.value.visible === true)) {
                                return true;
                            }
                            const filterConfig = configs.filter(e => e.dataset.toString() === dataset)

                            if ((filterConfig.length == 1) && (filterConfig[0].value.visible === false)) {
                                return false;
                            } else {
                                return true;
                            }
                        } catch (error) {
                            console.warn(error);
                            return true;
                        }
                    }

                    let style: Cesium.Cesium3DTileStyle;
                    let conditions: any[] = [];

                    if (colorBlendMode !== 'HIGHLIGHT') {
                        style = new Cesium.Cesium3DTileStyle({
                            color: {
                                evaluateColor: function (feature: Cesium.Cesium3DTileFeature, result: Cesium.Color | undefined) {
                                    return evaluateColor(feature, result);
                                },
                            },
                            show: {
                                evaluate: function (feature: Cesium.Cesium3DTileFeature) {
                                    return evaluateShow(feature);
                                },
                            },
                        });
                    } else {
                        style = new Cesium.Cesium3DTileStyle({
                            show: {
                                evaluate: function (feature: Cesium.Cesium3DTileFeature) {
                                    return evaluateShow(feature);
                                },
                            },
                        });
                    }
                    tileset.style = style;
                }
                styleUpdate();
                const styleUpdateEvent = this.dv(createNextAnimateFrameEvent(
                    sceneObject.layerConfigChanged,
                    sceneObject.colorBlendModeChanged,
                    sceneObject.visJsonChanged,
                ))
                this.d(styleUpdateEvent.don(() => { styleUpdate() }));
            }))

        }

    }
}
